package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.base.domain.User;
import cn.wolfcode.car.base.service.IUserService;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.BpmnInfoService;
import cn.wolfcode.car.business.service.CarPackageAuditService;
import cn.wolfcode.car.business.service.ServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.config.SystemConfig;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.math3.random.HaltonSequenceGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @Author WaveHi
 * @Date 12/11/2021 下午 3:07
 * @Version 1.0
 * @Contact HJBWaveHi@163.com
 * @Description
 */
@Service
public class ServiceItemServiceImpl extends ServiceImpl<ServiceItemMapper, ServiceItem> implements ServiceItemService {

//    @Autowired
//    private ServiceItemMapper serviceItemMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private BpmnInfoService bpmnInfoService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private CarPackageAuditService carPackageAuditService;

    @Override
    public Boolean add(ServiceItem item) {
        if(item.getCarPackage()) {
            item.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        return save(item);
//        int insert = serviceItemMapper.insert(item);
//        return insert > 0;
    }

    @Override
    public Boolean update(ServiceItem serviceItem) {
        ServiceItem oldObj = getById(serviceItem.getId());
//        ServiceItem oldObj = this.getServiceItem(serviceItem.getId());
        //处于上架状态的商品不能修改
        if(ServiceItem.SALESTATUS_ON.equals(oldObj.getSaleStatus())){
            throw new BusinessException("上架服务项目不能修改，请下架后再修改");
        }else if(ServiceItem.AUDITSTATUS_AUDITING.equals(oldObj.getAuditStatus())){
            throw new BusinessException("服务项目正在审核中,不可修改");
        }
        //如果是审核通过，此时修改，需要将其状态变更为初始化
        if(ServiceItem.AUDITSTATUS_APPROVED.equals(oldObj.getAuditStatus())){
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        return updateById(serviceItem);
//        int i = serviceItemMapper.updateByPrimaryKey(serviceItem);
//        return i > 0;
    }

    @Override
    public Boolean delete(Long id) {
        return removeById(id);
//        int i = serviceItemMapper.deleteByPrimaryKey(id);
//        return i > 0;
    }

    @Override
    public ServiceItem getServiceItem(Long id) {
        return getById(id);
//        return serviceItemMapper.selectByPrimaryKey(id);
    }

    @Override
    public List<ServiceItem> getAllServiceItem() {
        return list();
//        return serviceItemMapper.selectAll();
    }

    @Override
    public PageInfo<ServiceItem> getPartOfServiceItem(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        return new PageInfo<>(list());
//        return new PageInfo<>(serviceItemMapper.selectAll());
    }

    @Override
    public TablePageInfo<ServiceItem> getPartOfServiceItem(ServiceItemQuery serviceItemQuery) {
        QueryWrapper<ServiceItem> serviceItemQueryWrapper = new QueryWrapper<>();
        serviceItemQueryWrapper
                .like(serviceItemQuery.getName() != null,
                        "name",
                        serviceItemQuery.getName())
                .eq(serviceItemQuery.getCarPackage() != null,
                        "car_package",
                        serviceItemQuery.getCarPackage())
                .eq(serviceItemQuery.getServiceCatalog() != null,
                        "service_catalog",
                        serviceItemQuery.getServiceCatalog())
                .eq(serviceItemQuery.getAuditStatus() != null,
                        "audit_status",
                        serviceItemQuery.getAuditStatus())
                .eq(serviceItemQuery.getSaleStatus() != null,
                        "sale_status",
                        serviceItemQuery.getSaleStatus())
                .eq(serviceItemQuery.getDiscountPrice() != null,
                        "discount_price",
                        serviceItemQuery.getDiscountPrice());
        return new TablePageInfo<>(list(serviceItemQueryWrapper));
//        return new TablePageInfo<>(serviceItemMapper.selectByCondition(serviceItemQuery));
    }

    @Override
    public TablePageInfo<ServiceItem> getPartOfServiceItem(Integer pageNo, Integer pageSize, ServiceItemQuery serviceItemQuery) {
        PageHelper.startPage(pageNo, pageSize);
        QueryWrapper<ServiceItem> serviceItemQueryWrapper = new QueryWrapper<>();
        serviceItemQueryWrapper
                .like(serviceItemQuery.getName() != null,
                        "name",
                        serviceItemQuery.getName())
                .eq(serviceItemQuery.getCarPackage() != null,
                        "car_package",
                        serviceItemQuery.getCarPackage())
                .eq(serviceItemQuery.getServiceCatalog() != null,
                        "service_catalog",
                        serviceItemQuery.getServiceCatalog())
                .eq(serviceItemQuery.getAuditStatus() != null,
                        "audit_status",
                        serviceItemQuery.getAuditStatus())
                .eq(serviceItemQuery.getSaleStatus() != null,
                        "sale_status",
                        serviceItemQuery.getSaleStatus())
                .eq(serviceItemQuery.getDiscountPrice() != null,
                        "discount_price",
                        serviceItemQuery.getDiscountPrice());
        return new TablePageInfo<>(list(serviceItemQueryWrapper));
//        return new TablePageInfo<>(serviceItemMapper.selectByCondition(serviceItemQuery));
    }

    @Override
    public void saleOff(Long id) {
        ServiceItem serviceItem = getById(id);
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);
        updateById(serviceItem);
//        ServiceItem serviceItem = this.getServiceItem(id);
//        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);
//        serviceItemMapper.updateByPrimaryKey(serviceItem);
    }

    @Override
    public void saleOn(Long id) {
        ServiceItem serviceItem = getById(id);
//        ServiceItem serviceItem = this.getServiceItem(id);
        //如果不是套餐，可以直接上架
        //如果是套餐，只有审核成功才能上架
        if(ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())
                && !ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())){
            throw new BusinessException("套餐服务项需要审核通过之后才能上架");
        }
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_ON);
        updateById(serviceItem);
//        serviceItemMapper.updateByPrimaryKey(serviceItem);
    }

    @Override
    public TablePageInfo<ServiceItem> getAllServiceItems() {
        return new TablePageInfo<>(list());
//        return new TablePageInfo<>(serviceItemMapper.selectAll());
    }

    @Override
    @Transactional
    public Boolean audit(Long id, Long bpmnInfoId, Long director, Long finance, String info) {
        //Get service item
        ServiceItem serviceItem = getById(id);
//        ServiceItem serviceItem = this.getServiceItem(id);
        //Get director
        User directorForId = userService.get(director);
        //Get financer
        User financer = null;
        if(finance != null) {
            financer = userService.get(finance);
        }
        //Get bpmnInfo
        BpmnInfo bpmnInfo = bpmnInfoService.getBpmnInfo(bpmnInfoId);
        //Set variables
        HashMap<String, Object> hashMap = new HashMap<>(16);
        if(finance != null) {
            hashMap.put("financer", financer.getUserName());
        }
        hashMap.put("director", directorForId.getUserName());
        hashMap.put("cutPrice", serviceItem.getDiscountPrice().doubleValue());
        hashMap.put("auditResult", true);
        //Change audit status of  service item
        serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_AUDITING);
        this.update(serviceItem);
        //Save car package audit record
        CarPackageAudit carPackageAudit = new CarPackageAudit();
        carPackageAudit.setAuditorId(director);
        carPackageAudit.setBpmnInfoId(bpmnInfoId);
        carPackageAudit.setCreateTime(new Date());
        carPackageAudit.setCreator(ShiroUtils.getUser().getUserName());
        carPackageAudit.setServiceItemId(id);
        carPackageAudit.setServiceItemInfo(serviceItem.getInfo());
        carPackageAudit.setServiceItemPrice(serviceItem.getOriginalPrice());
        carPackageAudit.setInstanceId(info);
        carPackageAuditService.add(carPackageAudit);
        //Start instance
        ProcessDefinition processDefinition = repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(bpmnInfo.getDeploymentId())
                .singleResult();
        ProcessInstance processInstance =
                runtimeService.startProcessInstanceByKey(
                        processDefinition.getKey(),
                        String.valueOf(carPackageAudit.getId()),
                        hashMap);
        //Update car package audit record
        carPackageAudit.setInstanceId(processInstance.getId());
        return carPackageAuditService.update(carPackageAudit);
    }

    @Override
    public Boolean changeAuditStatus(Long id, Integer status) {
        ServiceItem serviceItem = getById(id);
        serviceItem.setAuditStatus(status);
        return updateById(serviceItem);
//        ServiceItem serviceItem = serviceItemMapper.selectByPrimaryKey(id);
//        serviceItem.setAuditStatus(status);
//        return serviceItemMapper.updateByPrimaryKey(serviceItem) > 0;
    }
}
